﻿//
// Author: LADJEMI Mehdi
// SFEIR 2011
// PAK Project Version 0.0.5
// Last Modification Date 11/04/2011
//
//
//

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.IO;
using System.Linq;
using System.Web;
using System.Collections.Specialized;

namespace Paw.Services.Serializers
{
    

    [Serializable]
    public class SerializableMailAddress
    
    {
        String user;
        String host;
        String address;
        String displayName;

        /// <summary> 
        /// Serializing the mail address
        /// </summary>
        public static SerializableMailAddress GetSerializableMailAddress(MailAddress mailAddress)
        {
            if (mailAddress == null)
                return null;
            SerializableMailAddress serializedMailAddress = new SerializableMailAddress();

            serializedMailAddress.user = mailAddress.User;
            serializedMailAddress.host = mailAddress.Host;
            serializedMailAddress.address = mailAddress.Address;
            serializedMailAddress.displayName = mailAddress.DisplayName;

            return serializedMailAddress;
        }

        /// <summary>
        /// Returns the mail address
        /// </summary>
        /// <returns>original mail address</returns>
        public MailAddress GetOriginalMailAddress()
        {
            return new MailAddress(address, displayName);
        }

        /// <summary>
        /// Returns the mails addresses from lists
        /// </summary>
        /// <returns> mail addresses </returns>
        //public List<SerializableMailAddress> GetOriginalListMailAddress()
        //{ 
        //    return new List<SerializableMailAddress>(); 
        //}

    }

    [Serializable]
    public class SerializableAttachement
    {
    // TO DO if Needed
    }

    [Serializable]
    public class SerializableAlternateView
    {

        // TO DO if Needed
        internal static object GetSerializableAlternateView(AlternateView alternateView)
        {
            throw new NotImplementedException();
        }
    }

    [Serializable]
    public class SerializableCollection
    {


        // TO DO if Needed
        Dictionary<String, String> Collection = new Dictionary<String, String>();
        public SerializableCollection()
        {

        }

        public static SerializableCollection GetSerializableCollection(NameValueCollection col)
        {
            if (col == null)
                return null;

            SerializableCollection scol = new SerializableCollection();
            foreach (String key in col.Keys)
                scol.Collection.Add(key, col[key]);

            return scol;
        }

        public static SerializableCollection GetSerializableCollection(StringDictionary col)
        {
            if (col == null)
                return null;

            SerializableCollection scol = new SerializableCollection();
            foreach (String key in col.Keys)
                scol.Collection.Add(key, col[key]);

            return scol;
        }

        public void SetColletion(NameValueCollection scol)
        {

            foreach (String key in Collection.Keys)
            {
                scol.Add(key, this.Collection[key]);
            }

        }

        public void SetColletion(StringDictionary scol)
        {

            foreach (String key in Collection.Keys)
            {
                if (scol.ContainsKey(key))
                    scol[key] = Collection[key];
                else
                    scol.Add(key, this.Collection[key]);
            }
        }
    
    }

    [Serializable]
    public class SerializableLinkedResource
    {
        String contentID;
        Uri contentLink;
        Stream contentStream;
        SerializableContentType serializedContentType;
        TransferEncoding transferEncoding;

        /// <summary>
        /// Serializable Linked Resource
        /// </summary>
        /// <param name="linkedResource">Linked Resource that needs to be serialized</param>
        /// <returns>Serializable Linked Resource</returns>
        public static SerializableLinkedResource GetSerializableLinkedResource(LinkedResource linkedResource)
        {
            if (linkedResource == null)
                return null;

            SerializableLinkedResource serializedLinkedResource = new SerializableLinkedResource();
            serializedLinkedResource.contentID = linkedResource.ContentId;
            serializedLinkedResource.contentLink = linkedResource.ContentLink;

            if (linkedResource.ContentStream != null)
            {
                byte[] bytes = new byte[linkedResource.ContentStream.Length];
                linkedResource.ContentStream.Read(bytes, 0, bytes.Length);
                serializedLinkedResource.contentStream = new MemoryStream(bytes);
            }

            serializedLinkedResource.serializedContentType = SerializableContentType.GetSerializableContentType(linkedResource.ContentType);
            serializedLinkedResource.transferEncoding = linkedResource.TransferEncoding;

            return serializedLinkedResource;

        }

        /// <summary>
        /// Gets original Linked Resource
        /// </summary>
        /// <returns>original linked resource</returns>
        public LinkedResource GetOriginalLinkedResource()
        {
            LinkedResource linkedResource = new LinkedResource(contentStream);
            linkedResource.ContentId = contentID;
            linkedResource.ContentLink = contentLink;

            linkedResource.ContentType = serializedContentType.GetOriginalContentType();
            linkedResource.TransferEncoding = transferEncoding;

            return linkedResource;
        }
    }

    [Serializable]
    public class SerializableMailMessage
    {
        public string MailID { get; set; }
        Boolean isBodyHtml { get; set; }
        String body { get; set; } 
        SerializableMailAddress serializedFrom { get; set; }
        List<SerializableMailAddress> serializedTo = new List<SerializableMailAddress>();
        List<SerializableMailAddress> serializedCc = new List<SerializableMailAddress>();
        List<SerializableMailAddress> serializedBcc = new List<SerializableMailAddress>();
        List<SerializableMailAddress> serializedReplyToList = new List<SerializableMailAddress>(); 
        SerializableMailAddress serializedSender { get; set; }
        String subject { get; set;}
        
        // Attachement
        List<SerializableAttachement> serializedAttachement = new List<SerializableAttachement>();

        // Body and Subject Encoding
        Encoding bodyEncoding;
        Encoding subjectEncoding;

        // Priority
        MailPriority mailPriority;

        // Notification 
        DeliveryNotificationOptions serializedDeliveryNotificationOptions;

        // Headers
        //SerializableCollection serializedHeaders;

        // Alternate View
        List<SerializableAlternateView> serializableAlternateView = new List<SerializableAlternateView>();


        /// <summary>
        /// Serializable Mail Message Constructor
        /// </summary>
        /// <param name="mailMessage"></param>

        public SerializableMailMessage(MailMessage mailMessage)
        {
        
            // TO DO

            MailID = Guid.NewGuid().ToString();
            isBodyHtml = mailMessage.IsBodyHtml;
            body = mailMessage.Body;
            subject = mailMessage.Subject;
            subjectEncoding = mailMessage.SubjectEncoding;
            bodyEncoding = mailMessage.BodyEncoding;
            serializedDeliveryNotificationOptions = mailMessage.DeliveryNotificationOptions;
            // Headers TO DO
            //serializedHeaders = SerializableCollection.GetSerializableCollection(mailMessage.Headers);
            mailPriority = mailMessage.Priority;
            serializedSender = SerializableMailAddress.GetSerializableMailAddress(mailMessage.Sender);

            serializedTo = new List<SerializableMailAddress>();
            foreach (MailAddress mailaddress in mailMessage.To)
            {
                serializedTo.Add(SerializableMailAddress.GetSerializableMailAddress(mailaddress));
            }


            serializedReplyToList = new List<SerializableMailAddress>();
            foreach (MailAddress mailaddress in mailMessage.ReplyToList)
            {
                serializedReplyToList.Add(SerializableMailAddress.GetSerializableMailAddress(mailaddress));
            }
            

            serializedCc = new List<SerializableMailAddress>();
            foreach (MailAddress mailaddress in mailMessage.CC)
            {
                serializedCc.Add(SerializableMailAddress.GetSerializableMailAddress(mailaddress));
            }

            serializedBcc = new List<SerializableMailAddress>();
            foreach (MailAddress mailaddress in mailMessage.Bcc)
            {
                serializedBcc.Add(SerializableMailAddress.GetSerializableMailAddress(mailaddress));
            }

            //serializableAlternateView = new List<SerializableAlternateView>();
        }

        /// <summary>
        /// Returns the MailMessge object from the serializeable object
        /// </summary>
        /// <returns>Original Mail Message Object</returns>
        public MailMessage GetOriginalMailObject()
        {
            MailMessage mailMsg = new MailMessage();

            mailMsg.IsBodyHtml = isBodyHtml;
            mailMsg.Body = body;
            mailMsg.Subject = subject;
            if (serializedFrom != null)
                mailMsg.From = serializedFrom.GetOriginalMailAddress();

            if (serializedTo != null)
            foreach (SerializableMailAddress serializedMailToAddr in serializedTo)
            {
                mailMsg.To.Add(serializedMailToAddr.GetOriginalMailAddress());
            }

            if (serializedCc != null)
            foreach (SerializableMailAddress serializedMailCCAddr in serializedCc)
            {
                mailMsg.CC.Add(serializedMailCCAddr.GetOriginalMailAddress());
            }

            if (serializedBcc != null)
            foreach (SerializableMailAddress serializedMailBCCAddr in serializedBcc)
            {
                mailMsg.Bcc.Add(serializedMailBCCAddr.GetOriginalMailAddress());
            }

            if (serializedReplyToList != null)
            foreach (SerializableMailAddress serializedReplyToListAddr in serializedReplyToList)
            {
                mailMsg.To.Add(serializedReplyToListAddr.GetOriginalMailAddress());
            }


            mailMsg.BodyEncoding = bodyEncoding;

            mailMsg.DeliveryNotificationOptions = serializedDeliveryNotificationOptions;
            //serializedHeaders.SetColletion(mailMsg.Headers);
            mailMsg.Priority = mailPriority;
            
            if (serializedSender != null)
                mailMsg.Sender = serializedSender.GetOriginalMailAddress();

            mailMsg.SubjectEncoding = subjectEncoding;

            //foreach (SerializableAlternateView av in serializedAlternateViews)
            //    mailMsg.AlternateViews.Add(av.GetOriginalAlternateView());

            return mailMsg;
        }
            
    }

    /// <summary>
    /// Serializable Content Type
    /// </summary>
    [Serializable]
    public class SerializableContentType
    {
        String boundary;
        String charSet;
        String mediaType;
        String name;
        SerializableCollection serializedColParameters;

        /// <summary>
        /// Returns serializable content type
        /// </summary>
        /// <param name="contentType">Original content type</param>
        /// <returns>serialized content type</returns>
        public static SerializableContentType GetSerializableContentType(System.Net.Mime.ContentType contentType)
        {
            if (contentType == null)
                return null;

            SerializableContentType serializedContentType = new SerializableContentType();

            serializedContentType.name = contentType.Name;
            serializedContentType.boundary = contentType.Boundary;
            serializedContentType.mediaType = contentType.MediaType;
            serializedContentType.charSet = contentType.CharSet;

            serializedContentType.serializedColParameters = SerializableCollection.GetSerializableCollection(contentType.Parameters);

            return serializedContentType;
        }

        /// <summary>
        /// Returns Original ContentType
        /// </summary>
        /// <returns></returns>
        public ContentType GetOriginalContentType()
        {

            ContentType serializedContentType = new ContentType();

            serializedContentType.Boundary = boundary;
            serializedContentType.CharSet = charSet;
            serializedContentType.MediaType = mediaType;
            serializedContentType.Name = name;

            serializedColParameters.SetColletion(serializedContentType.Parameters);

            return serializedContentType;
        }
    }

}